Descripción del curso

El curso ofrecido por el Instituto Nacional de Estadísticas de Chile (INE) se centra en la importancia de manejar y analizar datos faltantes, que son una realidad en cualquier análisis de datos del mundo real. Los valores faltantes pueden aparecer por diversas razones, desde problemas de medición hasta problemas de calidad de los datos, y su presencia puede dificultar la comprensión y la interpretación de los análisis.

En este contexto, el curso del INE brinda a los participantes las habilidades y herramientas necesarias para manejar los datos faltantes de manera efectiva y mejorar la calidad de sus análisis. En particular, se utiliza el paquete R de naniar, una herramienta muy útil para explorar, visualizar y manejar valores faltantes en R.

El curso consta de varios capítulos, cada uno enfocado en un aspecto específico del manejo de datos faltantes. En el primer capítulo se aprende a detectar, contar y resumir la falta de datos, utilizando técnicas como la función is.na() y las funciones de resumen como sum(), mean(), entre otras. Además, se enseña cómo explorar los patrones de datos faltantes en diferentes variables y casos, y cómo detectar posibles sesgos y patrones subyacentes en los datos.

En los capítulos siguientes, se aborda la imputación de valores faltantes, es decir, cómo llenar los vacíos en los datos utilizando diferentes técnicas de imputación, como la imputación por media, la imputación múltiple y la regresión de los valores faltantes. También se aprende a evaluar la calidad de los datos imputados y a tomar decisiones basadas en estos conjuntos de datos imputados.

Además, el curso incluye una sección dedicada a la visualización de datos faltantes, donde se aprende a producir visualizaciones generales para todo el conjunto de datos y para las variables, casos y otros resúmenes, y cómo explorar estos en los grupos.

En resumen, el curso del INE proporciona las habilidades y herramientas necesarias para manejar, explorar y analizar datos faltantes de manera efectiva y mejorar la calidad de los análisis de datos del mundo real.

#Capitulo 1

Introducción a los datos perdidos

Trasncripción

  1. Introducción a los datos faltantes Para este curso se utilizarán herramientas como tidyverse y el paquete R de naniar para enseñar a manejar y analizar datos faltantes de manera efectiva. El paquete naniar es una herramienta muy útil para explorar, visualizar y manejar valores faltantes en R.

  2. Introducción La estadística Gertrude Mary Cox dijo una vez: “Lo mejor que se puede hacer con los datos faltantes es no tener ninguno”. Si bien esto es cierto, no es el mundo en el que vivimos. Trabajar con datos del mundo real significa trabajar con datos faltantes. Para ser un gran analista, necesitas saber cómo lidiar con los valores faltantes. Comprender cómo funcionan los datos faltantes es importante, ya que pueden tener efectos inesperados en tu análisis. Por ejemplo, ajustar un modelo lineal en datos con valores faltantes elimina fragmentos de datos. Esto significa que tus decisiones no se basan en la evidencia correcta. Reemplazar los valores faltantes, lo que se llama imputación, debe hacerse con mucho cuidado, ya que insertar solo la media puede llevar a estimaciones y decisiones deficientes.

  3. ¿Qué aprenderás? En este curso aprenderás sobre qué son los valores faltantes, cómo encontrar datos faltantes, cómo manipular y limpiar datos faltantes, por qué faltan datos y cómo imputar valores faltantes.

  4. Conocimientos previos Para este curso, asumiré que tienes experiencia básica a intermedia con R, experiencia en la creación de gráficos utilizando ggplot2, experiencia en el uso de dplyr para manipular datos y experiencia en ajustar modelos lineales en R. En este primer capítulo, presentamos los valores faltantes y cómo verificarlos y contarlos.

  5. ¿Qué son los valores faltantes? Antes de comenzar, debemos definir los valores faltantes. Los valores faltantes son valores que deberían haberse registrado, pero no lo fueron. Piensa en esto de esta manera: puedes no haber registrado accidentalmente que viste un pájaro, esto es un valor faltante. Esto es diferente a registrar que no se observaron pájaros. R almacena los valores faltantes como NA, que significa no disponible.

  6. ¿Cómo puedo verificar si tengo valores faltantes? Los valores faltantes no saltan y gritan “¡Estoy aquí!”. Por lo general, están ocultos, como una aguja en un pajar. Para detectar valores faltantes, usa any_na, que devuelve TRUE si hay valores faltantes y FALSE si no los hay. are_na pregunta “¿son estos NA?” y devuelve TRUE/FALSE para cada valor. are_na nos muestra 3 valores TRUE, que corresponden a 3 valores faltantes. Para evitar contar cada TRUE manualmente, n_miss cuenta el número de valores faltantes. Y prop_miss proporciona la proporción de valores faltantes, lo que proporciona un contexto importante: ¡el 50% de los datos está faltando!

  7. Trabajando con datos faltantes ¿Qué sucede cuando mezclamos valores faltantes con nuestros cálculos? Necesitamos saber qué sucede para poder estar preparados para encontrar estos casos. La regla general es: Los cálculos con NA devuelven NA. Digamos que tienes la altura de tres amigos: Sophie, Dan y Fred. La suma de sus alturas devuelve NA, esto se debe a que no conocemos la suma de un número y NA.

  8. Trampas con datos faltantes Hay algunas “trampas” que debes tener en cuenta al trabajar con datos faltantes: Por ejemplo, NaN significa “Not a Number” (No es un número) y se obtiene de operaciones como la raíz cuadrada de -1. R interpreta NaN como un valor faltante. NULL es un valor vacío pero no es faltante. Esto es sutilmente diferente de los valores faltantes: un cubo vacío no tiene agua faltante. Inf es un valor infinito, y se obtiene de ecuaciones como 10 dividido por 0 y no es faltante.

  9. Trampas con datos faltantes (2) Por último, ten cuidado con las declaraciones condicionales con valores faltantes. Por ejemplo, NA o TRUE es TRUE. NA o FALSE es NA. NA + NaN es NA. NaN + NA es NaN.

¡Practiquemos! ¡Practiquemos!

##Usando y encontrando valores faltantes

Al trabajar con datos faltantes, hay algunos comandos con los que deberías estar familiarizado - en primer lugar, debes poder identificar si hay valores faltantes y dónde se encuentran.

Usando las herramientas any_na() y are_na(), identifica qué valores faltan.

# Create x, a vector, with values NA, NaN, Inf, ".", and "missing"
x <- c(NA, NaN,Inf, ".", "missing")

# Use any_na() and are_na() on to explore the missings
any_na(x)
## [1] TRUE
are_na(x)
## [1]  TRUE FALSE FALSE FALSE FALSE

###¿Cuántos valores faltantes hay?

Una de las primeras cosas que desearás comprobar en un nuevo conjunto de datos es si existen valores faltantes y cuántos hay.

Podrías usar are_na() y contar los valores faltantes, pero la forma más eficiente de contarlos es usar la función n_miss(). Esto te dirá el número total de valores faltantes en los datos.

Luego puedes encontrar el porcentaje de valores faltantes en los datos con la función pct_miss. Esto te dirá el porcentaje de valores faltantes en los datos.

También puedes encontrar el complemento de estos valores, cuántos valores completos hay, usando n_complete y pct_complete.

# Using the example dataframe of heights and weights dat_hw
dat_hw <- read.table("~/edi_imp/datacamp_JB/dealing/dat_hw.txt", h=T,  dec=".")
# Use n_miss() to count the total number of missing values in dat_hw
naniar::n_miss(dat_hw)
## [1] 30
# Use n_miss() on dat_hw$weight to count the total number of missing values
naniar::n_miss(dat_hw$weight)
## [1] 15
# Use n_complete() on dat_hw to count the total number of complete values
n_complete(dat_hw)
## [1] 170
# Use n_complete() on dat_hw$weight to count the total number of complete values
n_complete(dat_hw$weight)
## [1] 85
# Use prop_miss() and prop_complete() on dat_hw to count the total number of missing values in each of the variables
prop_miss(dat_hw)
## [1] 0.15
prop_complete(dat_hw)
## [1] 0.85

Como resumir valores perdidos

###Resumiendo la ausencia de datos

Ahora que comprendes el comportamiento de los valores faltantes en R y cómo contarlos, escalaremos nuestros resúmenes para casos (filas) y variables, utilizando miss_var_summary() y miss_case_summary(), y también exploraremos cómo se pueden aplicar a grupos en un dataframe utilizando la función group_by de dplyr.

# Summarise missingness in each variable of the `airquality` dataset
miss_var_summary(airquality)
## # A tibble: 6 × 3
##   variable n_miss pct_miss
##   <chr>     <int>    <dbl>
## 1 Ozone        37    24.2 
## 2 Solar.R       7     4.58
## 3 Wind          0     0   
## 4 Temp          0     0   
## 5 Month         0     0   
## 6 Day           0     0
# Summarise missingness in each case of the `airquality` dataset
miss_case_summary(airquality)
## # A tibble: 153 × 3
##     case n_miss pct_miss
##    <int>  <int>    <dbl>
##  1     5      2     33.3
##  2    27      2     33.3
##  3     6      1     16.7
##  4    10      1     16.7
##  5    11      1     16.7
##  6    25      1     16.7
##  7    26      1     16.7
##  8    32      1     16.7
##  9    33      1     16.7
## 10    34      1     16.7
## # … with 143 more rows
# Return the summary of missingness in each variable, grouped by Month, in the `airquality` dataset
airquality %>% group_by(Month) %>% miss_var_summary()
## # A tibble: 25 × 4
## # Groups:   Month [5]
##    Month variable n_miss pct_miss
##    <int> <chr>     <int>    <dbl>
##  1     5 Ozone         5     16.1
##  2     5 Solar.R       4     12.9
##  3     5 Wind          0      0  
##  4     5 Temp          0      0  
##  5     5 Day           0      0  
##  6     6 Ozone        21     70  
##  7     6 Solar.R       0      0  
##  8     6 Wind          0      0  
##  9     6 Temp          0      0  
## 10     6 Day           0      0  
## # … with 15 more rows
# Return the summary of missingness in each case, grouped by Month, in the `airquality` dataset
airquality %>% group_by(Month) %>% miss_case_summary()
## # A tibble: 153 × 4
## # Groups:   Month [5]
##    Month  case n_miss pct_miss
##    <int> <int>  <int>    <dbl>
##  1     5     5      2       40
##  2     5    27      2       40
##  3     5     6      1       20
##  4     5    10      1       20
##  5     5    11      1       20
##  6     5    25      1       20
##  7     5    26      1       20
##  8     5     1      0        0
##  9     5     2      0        0
## 10     5     3      0        0
## # … with 143 more rows

###Tabulando los valores faltantes

Las sumarizaciones de los valores faltantes que acabamos de calcular nos dan el número y el porcentaje de observaciones faltantes para los casos y variables.

Otra manera de resumir los valores faltantes es mediante la tabulación del número de veces que hay 0, 1, 2, 3, valores faltantes en una variable o en un caso.

En este ejercicio, vamos a tabular el número de valores faltantes en cada caso y variable utilizando miss_var_table() y miss_case_table(), y también combinaremos estos resúmenes con el operador group_by de dplyr para explorar los resúmenes sobre una variable de agrupación en el conjunto de datos.

# Tabulate missingness in each variable and case of the `airquality` dataset
miss_case_table(airquality)
## # A tibble: 3 × 3
##   n_miss_in_case n_cases pct_cases
##            <int>   <int>     <dbl>
## 1              0     111     72.5 
## 2              1      40     26.1 
## 3              2       2      1.31
miss_var_table(airquality)
## # A tibble: 3 × 3
##   n_miss_in_var n_vars pct_vars
##           <int>  <int>    <dbl>
## 1             0      4     66.7
## 2             7      1     16.7
## 3            37      1     16.7
# Tabulate the missingness in each variable, grouped by Month, in the `airquality` dataset
airquality %>% group_by(Month) %>% miss_var_table()
## # A tibble: 12 × 4
## # Groups:   Month [5]
##    Month n_miss_in_var n_vars pct_vars
##    <int>         <int>  <int>    <dbl>
##  1     5             0      3       60
##  2     5             4      1       20
##  3     5             5      1       20
##  4     6             0      4       80
##  5     6            21      1       20
##  6     7             0      4       80
##  7     7             5      1       20
##  8     8             0      3       60
##  9     8             3      1       20
## 10     8             5      1       20
## 11     9             0      4       80
## 12     9             1      1       20
# Tabulate of missingness in each case, grouped by Month, in the `airquality` dataset
airquality %>% group_by(Month) %>% miss_case_table()
## # A tibble: 11 × 4
## # Groups:   Month [5]
##    Month n_miss_in_case n_cases pct_cases
##    <int>          <int>   <int>     <dbl>
##  1     5              0      24     77.4 
##  2     5              1       5     16.1 
##  3     5              2       2      6.45
##  4     6              0       9     30   
##  5     6              1      21     70   
##  6     7              0      26     83.9 
##  7     7              1       5     16.1 
##  8     8              0      23     74.2 
##  9     8              1       8     25.8 
## 10     9              0      29     96.7 
## 11     9              1       1      3.33

###Otros resúmenes de valores faltantes

Algunos resúmenes de valores faltantes son particularmente útiles para diferentes tipos de datos. Por ejemplo, miss_var_span() y miss_var_run().

miss_var_span() calcula el número de valores faltantes en una variable especificada para un intervalo repetido. Esto es muy útil en datos de series de tiempo, para buscar patrones de valores faltantes semanales (de 7 días).

miss_var_run() calcula el número de “rachas” o “cadenas” de valores faltantes. Esto es útil para encontrar patrones inusuales de valores faltantes, por ejemplo, podría encontrar un patrón repetitivo de 5 completos y 5 faltantes.

Tanto miss_var_span() como miss_var_run() funcionan con el operador group_by de dplyr.

# Calculate the summaries for each run of missingness for the variable, hourly_counts
miss_var_run(pedestrian, var = hourly_counts)
## # A tibble: 35 × 2
##    run_length is_na   
##         <int> <chr>   
##  1       6628 complete
##  2          1 missing 
##  3       5250 complete
##  4        624 missing 
##  5       3652 complete
##  6          1 missing 
##  7       1290 complete
##  8        744 missing 
##  9       7420 complete
## 10          1 missing 
## # … with 25 more rows
# Calculate the summaries for each span of missingness, for a span of 4000, for the variable hourly_counts
miss_var_span(pedestrian, var = hourly_counts, span_every = 4000)
## # A tibble: 10 × 6
##    span_counter n_miss n_complete prop_miss prop_complete n_in_span
##           <int>  <int>      <int>     <dbl>         <dbl>     <int>
##  1            1      0       4000   0               1          4000
##  2            2      1       3999   0.00025         1.00       4000
##  3            3    121       3879   0.0302          0.970      4000
##  4            4    503       3497   0.126           0.874      4000
##  5            5    745       3255   0.186           0.814      4000
##  6            6      0       4000   0               1          4000
##  7            7      1       3999   0.00025         1.00       4000
##  8            8      0       4000   0               1          4000
##  9            9    745       3255   0.186           0.814      4000
## 10           10    432       1268   0.254           0.746      1700
# For each `month` variable, calculate the run of missingness for hourly_counts
pedestrian %>% group_by(month) %>% miss_var_run(var = hourly_counts)
## # A tibble: 51 × 3
## # Groups:   month [12]
##    month    run_length is_na   
##    <ord>         <int> <chr>   
##  1 January        2976 complete
##  2 February       2784 complete
##  3 March          2976 complete
##  4 April           888 complete
##  5 April           552 missing 
##  6 April          1440 complete
##  7 May             744 complete
##  8 May              72 missing 
##  9 May            2160 complete
## 10 June           2880 complete
## # … with 41 more rows
# For each `month` variable, calculate the span of missingness of a span of 2000, for the variable hourly_counts
pedestrian %>% group_by(month) %>% miss_var_span(var = hourly_counts, span_every = 2000)
## # A tibble: 25 × 7
## # Groups:   month [12]
##    month    span_counter n_miss n_complete prop_miss prop_complete n_in_span
##    <ord>           <int>  <int>      <int>     <dbl>         <dbl>     <int>
##  1 January             1      0       2000     0             1          2000
##  2 January             2      0        976     0             1           976
##  3 February            1      0       2000     0             1          2000
##  4 February            2      0        784     0             1           784
##  5 March               1      0       2000     0             1          2000
##  6 March               2      0        976     0             1           976
##  7 April               1    552       1448     0.276         0.724      2000
##  8 April               2      0        880     0             1           880
##  9 May                 1     72       1928     0.036         0.964      2000
## 10 May                 2      0        976     0             1           976
## # … with 15 more rows

Como podemos visualizar los valores perdidos?

###Sus primeras visualizaciones de datos faltantes

Puede resultar difícil determinar dónde están los valores faltantes en sus datos, y aquí es donde la visualización realmente puede ayudar.

La función vis_miss() crea una visualización general de la falta de datos en los datos. También tiene opciones para agrupar filas según la falta de datos, usando cluster = TRUE; así como opciones para ordenar las columnas, desde las más faltantes hasta las menos faltantes (sort_miss = TRUE).

# Visualize all of the missingness in the `riskfactors`  dataset
vis_miss(riskfactors)
## Warning: `gather_()` was deprecated in tidyr 1.2.0.
## Please use `gather()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.

# Visualize and cluster all of the missingness in the `riskfactors` dataset
vis_miss(riskfactors, cluster  = TRUE)

# visualise and sort the columns by missingness in the `riskfactors` dataset
vis_miss(riskfactors, sort_miss  = TRUE)

###Visualización de casos y variables faltantes

Para obtener una imagen clara de los valores faltantes en las variables y casos, utiliza gg_miss_var() y gg_miss_case(). Estas son las versiones visuales de miss_var_summary() y miss_case_summary().

Estos pueden dividirse en múltiples gráficos, uno para cada categoría, eligiendo una variable para segmentar por ella.

# Visualize the number of missings in cases using `gg_miss_case()`
gg_miss_case(riskfactors)

# Explore the number of missings in cases using `gg_miss_case()` and facet by the variable `education`
gg_miss_case(riskfactors, facet = education)

# Visualize the number of missings in variables using `gg_miss_var()`
gg_miss_var(riskfactors)
## Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please
## use `guide = "none"` instead.

# Explore the number of missings in variables using `gg_miss_var()` and facet by the variable `education`
gg_miss_var(riskfactors, facet = education)
## Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please
## use `guide = "none"` instead.

##Visualizando patrones de datos faltantes

Practiquemos algunas formas diferentes de visualizar patrones de datos faltantes usando:

gg_miss_upset() para mostrar un patrón general de datos faltantes. gg_miss_fct() para un conjunto de datos que tiene un factor de interés: el matrimonio. y gg_miss_span() para explorar los datos faltantes en un conjunto de datos de series de tiempo. ¿Qué notas sobre los datos faltantes y la segmentación en los datos?

# Using the airquality dataset, explore the missingness pattern using gg_miss_upset()
gg_miss_upset(airquality)

# With the riskfactors dataset, explore how the missingness changes across the marital variable using gg_miss_fct()
gg_miss_fct(x = riskfactors, fct = marital)

# Using the pedestrian dataset, explore how the missingness of hourly_counts changes over a span of 3000 
gg_miss_span(pedestrian, var = hourly_counts, span_every = 3000)

# Using the pedestrian dataset, explore the impact of month by facetting by month
# and explore how missingness changes for a span of 1000
gg_miss_span(pedestrian, var = hourly_counts , span_every = 1000, facet = month)

#Limpieza y organización de valores faltantes

En el capítulo dos, aprenderás cómo descubrir valores faltantes ocultos como “missing” o “N/A” y reemplazarlos con NA. Aprenderás cómo manejar de manera eficiente los valores faltantes implícitos: aquellos valores que se dan por sentados como faltantes pero que no se enumeran explícitamente. También cubriremos cómo explorar la dependencia de datos faltantes, discutiendo Missing Completely at Random (MCAR), Missing At Random (MAR), Missing Not At Random (MNAR) y lo que significan para el análisis de tus datos.

##Búsqueda y reemplazo de valores faltantes

###Usando miss_scan_count

Tienes un conjunto de datos con valores faltantes codificados como "N/A", "missing" y "na". Pero antes de seguir adelante y comenzar a reemplazarlos con NA, deberíamos tener una idea de qué tan grande es el problema.

Utiliza miss_scan_count para contar los valores faltantes posibles en el conjunto de datos pacman, que contiene tres columnas:

year: el año en que la persona obtuvo esa puntuación. initial: las iniciales de la persona. score: las puntuaciones de esa persona.

# Using the example dataframe
pacman<-readRDS("~/edi_imp/datacamp_JB/dealing/pacman.rds")
# Explore the strange missing values "N/A"
miss_scan_count(data = pacman, search = list("N/A"))
## # A tibble: 6 × 2
##   Variable     n
##   <chr>    <int>
## 1 year         0
## 2 month        0
## 3 day          0
## 4 initial      0
## 5 score      100
## 6 country      0
# Explore the strange missing values "missing"
miss_scan_count(data = pacman, search = list("missing"))
## # A tibble: 6 × 2
##   Variable     n
##   <chr>    <int>
## 1 year        93
## 2 month       93
## 3 day         93
## 4 initial      0
## 5 score        0
## 6 country      0
# Explore the strange missing values "na"
miss_scan_count(data = pacman, search = list("na"))
## # A tibble: 6 × 2
##   Variable     n
##   <chr>    <int>
## 1 year       100
## 2 month      100
## 3 day        100
## 4 initial      0
## 5 score        0
## 6 country      0
# Explore the strange missing values " " (a single space)
miss_scan_count(data = pacman, search = list(" "))
## # A tibble: 6 × 2
##   Variable     n
##   <chr>    <int>
## 1 year         0
## 2 month        0
## 3 day          0
## 4 initial      0
## 5 score        0
## 6 country    100
# Explore all of the strange missing values, "N/A", "missing", "na", " "
miss_scan_count(data = pacman, search = list("N/A", "missing","na", " "))
## # A tibble: 6 × 2
##   Variable     n
##   <chr>    <int>
## 1 year       193
## 2 month      193
## 3 day        193
## 4 initial      0
## 5 score      100
## 6 country    100

###Usando replace_with_na

Siguiendo con el conjunto de datos anterior, ahora sabemos que tenemos algunos valores faltantes extraños.

Ahora, vamos a hacer algo al respecto y reemplazar estos valores con valores faltantes (por ejemplo, NA) usando la función replace_with_na().

# Print the top of the pacman data using `head()`
head(pacman)
## # A tibble: 6 × 6
##   year  month day   initial score   country
##   <chr> <chr> <chr> <chr>   <chr>   <chr>  
## 1 2007  10    27    LEX     2065812 "CA"   
## 2 1995  8     23    PNY     1163465 "JP"   
## 3 1980  2     8     MBJ     175380  " "    
## 4 1982  5     9     QRC     2025632 "ES"   
## 5 na    na    na    YPZ     925357  "NZ"   
## 6 2013  11    15    RVJ     319733  "AU"
# Replace the strange missing values "N/A", "na", and 
# "missing" with `NA` for the variables, year, and score
pacman_clean <- replace_with_na(pacman, replace = list(year = c("N/A", "na", "missing"),
                                score = c("N/A", "na", "missing")))
                                        
# Test if `pacman_clean` still has these values in it?
miss_scan_count(pacman_clean, search = list("N/A", "na", "missing"))
## # A tibble: 6 × 2
##   Variable     n
##   <chr>    <int>
## 1 year         0
## 2 month      193
## 3 day        193
## 4 initial      0
## 5 score        0
## 6 country      0

###Usando las variantes “scoped” de replace_with_na

Para reducir la repetición de código al reemplazar valores con NA, utiliza las variantes “scoped” de replace_with_na():

replace_with_na_at() replace_with_na_if() replace_with_na_all()

La sintaxis de reemplazo se ve así:

~.x == "N/A" Esto reemplaza todos los casos que son iguales a "N/A".

~.x %in% c("N/A", "missing", "na", " ") Reemplaza todos los casos que tienen "N/A", "missing", "na" o " ".

# Use `replace_with_na_at()` to replace with NA
replace_with_na_at(pacman,
                   .vars = c("year", "month", "day"), 
                   ~.x %in% c("N/A", "missing", "na", " "))
## # A tibble: 2,000 × 6
##    year  month day   initial score   country
##    <chr> <chr> <chr> <chr>   <chr>   <chr>  
##  1 2007  10    27    LEX     2065812 "CA"   
##  2 1995  8     23    PNY     1163465 "JP"   
##  3 1980  2     8     MBJ     175380  " "    
##  4 1982  5     9     QRC     2025632 "ES"   
##  5 <NA>  <NA>  <NA>  YPZ     925357  "NZ"   
##  6 2013  11    15    RVJ     319733  "AU"   
##  7 2003  12    4     VKD     3322668 "US"   
##  8 2016  9     9     ZIS     2137806 "CN"   
##  9 2013  3     20    IYD     3059716 "CN"   
## 10 1993  5     19    CHQ     231892  "AU"   
## # … with 1,990 more rows
# Use `replace_with_na_if()` to replace with NA the character values using `is.character`
replace_with_na_if(pacman,
                   .predicate = is.character, 
                   ~.x %in% c("N/A", "missing", "na", " "))
## # A tibble: 2,000 × 6
##    year  month day   initial score   country
##    <chr> <chr> <chr> <chr>   <chr>   <chr>  
##  1 2007  10    27    LEX     2065812 CA     
##  2 1995  8     23    PNY     1163465 JP     
##  3 1980  2     8     MBJ     175380  <NA>   
##  4 1982  5     9     QRC     2025632 ES     
##  5 <NA>  <NA>  <NA>  YPZ     925357  NZ     
##  6 2013  11    15    RVJ     319733  AU     
##  7 2003  12    4     VKD     3322668 US     
##  8 2016  9     9     ZIS     2137806 CN     
##  9 2013  3     20    IYD     3059716 CN     
## 10 1993  5     19    CHQ     231892  AU     
## # … with 1,990 more rows
# Use `replace_with_na_all()` to replace with NA
replace_with_na_all(pacman, ~.x %in% c("N/A", "missing", "na", " "))
## # A tibble: 2,000 × 6
##    year  month day   initial score   country
##    <chr> <chr> <chr> <chr>   <chr>   <chr>  
##  1 2007  10    27    LEX     2065812 CA     
##  2 1995  8     23    PNY     1163465 JP     
##  3 1980  2     8     MBJ     175380  <NA>   
##  4 1982  5     9     QRC     2025632 ES     
##  5 <NA>  <NA>  <NA>  YPZ     925357  NZ     
##  6 2013  11    15    RVJ     319733  AU     
##  7 2003  12    4     VKD     3322668 US     
##  8 2016  9     9     ZIS     2137806 CN     
##  9 2013  3     20    IYD     3059716 CN     
## 10 1993  5     19    CHQ     231892  AU     
## # … with 1,990 more rows

##Rellenando valores faltantes hacia abajo (cap2_s2)

###Arreglando valores faltantes implícitos usando complete()

Vamos a explorar un nuevo conjunto de datos, frogger.

Este conjunto de datos contiene 4 puntuaciones por jugador registradas en diferentes momentos: morning, afternoon, evening y late_night.

Cada jugador debería haber jugado 4 partidas, una en cada uno de estos momentos, pero parece que no todos los jugadores completaron todos estos juegos.

Utiliza la función complete() para hacer explícitos estos valores faltantes implícitos.

frogger <- read_excel("~/edi_imp/datacamp_JB/dealing/frogger.xlsx")
# Print the frogger data to have a look at it
frogger
## # A tibble: 15 × 3
##    name  time       value 
##    <chr> <chr>      <chr> 
##  1 jesse morning    6678  
##  2 jesse afternoon  800060
##  3 jesse evening    475528
##  4 jesse late_night 143533
##  5 andy  morning    425115
##  6 andy  afternoon  587468
##  7 andy  late_night 111000
##  8 nic   afternoon  588532
##  9 nic   late_night 915533
## 10 dan   morning    388148
## 11 dan   evening    180912
## 12 alex  morning    552670
## 13 alex  afternoon  98355 
## 14 alex  evening    266055
## 15 alex  late_night 121056
# Use `complete()` on the `time` and `name` variables to  
# make implicit missing values explicit
frogger_tidy <- frogger %>% complete(time, name)

###Arreglando valores faltantes explícitos usando fill()

Un tipo de valor faltante que puede ser obvio de tratar es donde se da la primera entrada de un grupo, pero las entradas subsiguientes están marcadas como NA.

Estos valores faltantes a menudo son el resultado de valores vacíos en hojas de cálculo para evitar ingresar múltiples nombres varias veces; así como para “legibilidad humana”.

Este tipo de problema se puede resolver utilizando la función fill() del paquete tidyr.

# Print the frogger data to have a look at it
frogger
## # A tibble: 15 × 3
##    name  time       value 
##    <chr> <chr>      <chr> 
##  1 jesse morning    6678  
##  2 jesse afternoon  800060
##  3 jesse evening    475528
##  4 jesse late_night 143533
##  5 andy  morning    425115
##  6 andy  afternoon  587468
##  7 andy  late_night 111000
##  8 nic   afternoon  588532
##  9 nic   late_night 915533
## 10 dan   morning    388148
## 11 dan   evening    180912
## 12 alex  morning    552670
## 13 alex  afternoon  98355 
## 14 alex  evening    266055
## 15 alex  late_night 121056
# Use `fill()` to fill down the name variable in the frogger dataset
frogger %>% fill(name)
## # A tibble: 15 × 3
##    name  time       value 
##    <chr> <chr>      <chr> 
##  1 jesse morning    6678  
##  2 jesse afternoon  800060
##  3 jesse evening    475528
##  4 jesse late_night 143533
##  5 andy  morning    425115
##  6 andy  afternoon  587468
##  7 andy  late_night 111000
##  8 nic   afternoon  588532
##  9 nic   late_night 915533
## 10 dan   morning    388148
## 11 dan   evening    180912
## 12 alex  morning    552670
## 13 alex  afternoon  98355 
## 14 alex  evening    266055
## 15 alex  late_night 121056

###Usando complete() y fill() juntos

¡Ahora pongámoslo todo junto!

Utiliza complete() y fill() juntos para corregir valores faltantes explícitos e implícitos en el conjunto de datos frogger.

# Print the frogger data to have a look at it
frogger
## # A tibble: 15 × 3
##    name  time       value 
##    <chr> <chr>      <chr> 
##  1 jesse morning    6678  
##  2 jesse afternoon  800060
##  3 jesse evening    475528
##  4 jesse late_night 143533
##  5 andy  morning    425115
##  6 andy  afternoon  587468
##  7 andy  late_night 111000
##  8 nic   afternoon  588532
##  9 nic   late_night 915533
## 10 dan   morning    388148
## 11 dan   evening    180912
## 12 alex  morning    552670
## 13 alex  afternoon  98355 
## 14 alex  evening    266055
## 15 alex  late_night 121056
# Correctly fill() and complete() missing values so that our dataset becomes sensible
frogger %>%
  fill(name) %>%
  complete(name, time)
## # A tibble: 20 × 3
##    name  time       value 
##    <chr> <chr>      <chr> 
##  1 alex  afternoon  98355 
##  2 alex  evening    266055
##  3 alex  late_night 121056
##  4 alex  morning    552670
##  5 andy  afternoon  587468
##  6 andy  evening    <NA>  
##  7 andy  late_night 111000
##  8 andy  morning    425115
##  9 dan   afternoon  <NA>  
## 10 dan   evening    180912
## 11 dan   late_night <NA>  
## 12 dan   morning    388148
## 13 jesse afternoon  800060
## 14 jesse evening    475528
## 15 jesse late_night 143533
## 16 jesse morning    6678  
## 17 nic   afternoon  588532
## 18 nic   evening    <NA>  
## 19 nic   late_night 915533
## 20 nic   morning    <NA>

##Dependencia de datos faltantes

###Diferencias entre MCAR y MAR

Necesitamos hacer ciertas suposiciones sobre nuestros datos cuando avanzamos en el análisis.

¿Cuál de las siguientes respuestas sobre MCAR y MAR es VERDADERA?

##Posibles respuestas

En general, eliminar observaciones es más seguro para datos MCAR que eliminar observaciones para datos MAR.

MCAR significa que la falta de datos está relacionada con los datos observados, mientras que para MAR, la falta de datos está relacionada con los datos no observados.

MAR y MCAR son efectivamente lo mismo, la distinción no es importante.

Los datos MCAR no están relacionados con los datos observados y no observados. Los datos MAR están relacionados con los datos observados.

###Explorando la dependencia de datos faltantes

Para aprender sobre la estructura de la falta de datos en los datos, puedes explorar cómo cambia la presentación de la falta de datos al ordenar los datos.

Para el conjunto de datos oceanbuoys, explora la falta de datos con vis_miss() y luego ordénalo por algunas variables diferentes.

Este no es un proceso definitivo, pero te ayudará a comenzar a hacer las preguntas correctas sobre tus datos. Exploramos técnicas más poderosas en el próximo capítulo.

# Arrange by year
oceanbuoys %>% arrange(year) %>% vis_miss()

# Arrange by latitude
oceanbuoys %>% arrange(latitude) %>% vis_miss()

# Arrange by wind_ew (wind east west)
oceanbuoys %>% arrange(wind_ew) %>% vis_miss()

###Explorando aún más la dependencia de los datos faltantes

Usando la información previa sobre el conjunto de datos oceanbuoys, ¿cuál de estas afirmaciones es la más apropiada sobre el tipo de datos faltantes?

Intenta usar gg_miss_var() y gg_miss_case(), agrupando por año para obtener más información. Por ejemplo:

library(naniar) gg_miss_var(oceanbuoys, facet = year)

Posibles respuestas:

Los datos son MCAR: la dirección del viento es importante para explicar los datos faltantes.

Los datos son MCAR: el año es importante para explicar los datos faltantes.

Los datos son MAR: la ubicación no es importante para explicar los datos faltantes.

Los datos son MAR: tanto el año como la ubicación son importantes para explicar los datos faltantes.

#Capítulo 2

##Herramientas para explorar la dependencia de los datos faltantes

###Creando datos de matriz de sombra

Los datos faltantes pueden ser complicados de pensar, ya que normalmente no se proclaman por sí mismos y en su lugar se esconden entre la maleza de los datos.

Una forma de ayudar a exponer los valores faltantes es cambiar la forma en que pensamos sobre los datos, pensando en cada valor de datos como faltante o no faltante.

La función as_shadow() en R transforma un dataframe en una matriz de sombra, un formato de datos especial donde los valores son o bien faltantes (NA) o no faltantes (!NA).

Los nombres de columna de una matriz de sombra son los mismos que los datos, pero tienen un sufijo agregado _NA.

Para realizar un seguimiento y comparar los valores de los datos con su estado de falta, use la función bind_shadow(). Tener los datos en este formato, con la columna de matriz de sombra unida a los datos regulares, se llama datos nabular.

# Create shadow matrix data with `as_shadow()`
as_shadow(oceanbuoys)
## # A tibble: 736 × 8
##    year_NA latitude_NA longitude_NA sea_temp_c…¹ air_t…² humid…³ wind_…⁴ wind_…⁵
##    <fct>   <fct>       <fct>        <fct>        <fct>   <fct>   <fct>   <fct>  
##  1 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
##  2 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
##  3 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
##  4 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
##  5 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
##  6 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
##  7 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
##  8 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
##  9 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
## 10 !NA     !NA         !NA          !NA          !NA     !NA     !NA     !NA    
## # … with 726 more rows, and abbreviated variable names ¹​sea_temp_c_NA,
## #   ²​air_temp_c_NA, ³​humidity_NA, ⁴​wind_ew_NA, ⁵​wind_ns_NA
# Create nabular data by binding the shadow to the data with `bind_shadow()`
bind_shadow(oceanbuoys)
## # A tibble: 736 × 16
##     year latit…¹ longi…² sea_t…³ air_t…⁴ humid…⁵ wind_ew wind_ns year_NA latit…⁶
##    <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl> <fct>   <fct>  
##  1  1997       0    -110    27.6    27.1    79.6   -6.40    5.40 !NA     !NA    
##  2  1997       0    -110    27.5    27.0    75.8   -5.30    5.30 !NA     !NA    
##  3  1997       0    -110    27.6    27      76.5   -5.10    4.5  !NA     !NA    
##  4  1997       0    -110    27.6    26.9    76.2   -4.90    2.5  !NA     !NA    
##  5  1997       0    -110    27.6    26.8    76.4   -3.5     4.10 !NA     !NA    
##  6  1997       0    -110    27.8    26.9    76.7   -4.40    1.60 !NA     !NA    
##  7  1997       0    -110    28.0    27.0    76.5   -2       3.5  !NA     !NA    
##  8  1997       0    -110    28.0    27.1    78.3   -3.70    4.5  !NA     !NA    
##  9  1997       0    -110    28.0    27.2    78.6   -4.20    5    !NA     !NA    
## 10  1997       0    -110    28.0    27.2    76.9   -3.60    3.5  !NA     !NA    
## # … with 726 more rows, 6 more variables: longitude_NA <fct>,
## #   sea_temp_c_NA <fct>, air_temp_c_NA <fct>, humidity_NA <fct>,
## #   wind_ew_NA <fct>, wind_ns_NA <fct>, and abbreviated variable names
## #   ¹​latitude, ²​longitude, ³​sea_temp_c, ⁴​air_temp_c, ⁵​humidity, ⁶​latitude_NA
# Bind only the variables with missing values by using bind_shadow(only_miss = TRUE)
bind_shadow(oceanbuoys, only_miss = TRUE)
## # A tibble: 736 × 11
##     year latit…¹ longi…² sea_t…³ air_t…⁴ humid…⁵ wind_ew wind_ns sea_t…⁶ air_t…⁷
##    <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl> <fct>   <fct>  
##  1  1997       0    -110    27.6    27.1    79.6   -6.40    5.40 !NA     !NA    
##  2  1997       0    -110    27.5    27.0    75.8   -5.30    5.30 !NA     !NA    
##  3  1997       0    -110    27.6    27      76.5   -5.10    4.5  !NA     !NA    
##  4  1997       0    -110    27.6    26.9    76.2   -4.90    2.5  !NA     !NA    
##  5  1997       0    -110    27.6    26.8    76.4   -3.5     4.10 !NA     !NA    
##  6  1997       0    -110    27.8    26.9    76.7   -4.40    1.60 !NA     !NA    
##  7  1997       0    -110    28.0    27.0    76.5   -2       3.5  !NA     !NA    
##  8  1997       0    -110    28.0    27.1    78.3   -3.70    4.5  !NA     !NA    
##  9  1997       0    -110    28.0    27.2    78.6   -4.20    5    !NA     !NA    
## 10  1997       0    -110    28.0    27.2    76.9   -3.60    3.5  !NA     !NA    
## # … with 726 more rows, 1 more variable: humidity_NA <fct>, and abbreviated
## #   variable names ¹​latitude, ²​longitude, ³​sea_temp_c, ⁴​air_temp_c, ⁵​humidity,
## #   ⁶​sea_temp_c_NA, ⁷​air_temp_c_NA

###Realizando resúmenes agrupados de valores faltantes

Ahora que puedes crear datos nabulares, vamos a utilizarlos para explorar los datos. Vamos a calcular estadísticas de resumen basadas en los valores faltantes de otra variable.

Para hacer esto, vamos a seguir los siguientes pasos:

Primero, bind_shadow() convierte los datos en datos nabulares.

A continuación, realiza algunos resúmenes en los datos utilizando group_by() y summarize() para calcular la media y la desviación estándar, utilizando las funciones mean() y sd().

# `bind_shadow()` and `group_by()` humidity missingness (`humidity_NA`)
oceanbuoys %>%
  bind_shadow() %>%
  group_by(humidity_NA) %>%
  summarize(wind_ew_mean = mean(wind_ew), # calculate mean of wind_ew
            wind_ew_sd = sd(wind_ew)) # calculate standard deviation of wind_ew
## # A tibble: 2 × 3
##   humidity_NA wind_ew_mean wind_ew_sd
##   <fct>              <dbl>      <dbl>
## 1 !NA                -3.78       1.90
## 2 NA                 -3.30       2.31
# Repeat this, but calculating summaries for wind north south (`wind_ns`)
oceanbuoys %>%
  bind_shadow() %>%
  group_by(humidity_NA) %>%
  summarize(wind_ns_mean = mean(wind_ns),
            wind_ns_sd = sd(wind_ns))
## # A tibble: 2 × 3
##   humidity_NA wind_ns_mean wind_ns_sd
##   <fct>              <dbl>      <dbl>
## 1 !NA                 2.78       2.06
## 2 NA                  1.66       2.23

##Explorando combinaciones adicionales de valores faltantes

Puede ser útil obtener un poco de información adicional sobre el número de casos en cada condición de valores faltantes.

En este ejercicio, vamos a añadir información sobre el número de casos observados utilizando n() dentro de la función summarize().

Luego añadiremos un nivel adicional de agrupamiento al examinar la combinación de humedad faltante (humidity_NA) y temperatura del aire faltante (air_temp_c_NA).

# Summarize wind_ew by the missingness of `air_temp_c_NA`
oceanbuoys %>% 
  bind_shadow() %>%
  group_by(air_temp_c_NA) %>%
  summarize(wind_ew_mean = mean(wind_ew),
            wind_ew_sd = sd(wind_ew),
            n_obs = n())
## # A tibble: 2 × 4
##   air_temp_c_NA wind_ew_mean wind_ew_sd n_obs
##   <fct>                <dbl>      <dbl> <int>
## 1 !NA                  -3.91       1.85   655
## 2 NA                   -2.17       2.14    81
# Summarize wind_ew by missingness of `air_temp_c_NA` and `humidity_NA`
oceanbuoys %>% 
  bind_shadow() %>%
  group_by(air_temp_c_NA, humidity_NA) %>%
  summarize(wind_ew_mean = mean(wind_ew),
            wind_ew_sd = sd(wind_ew),
            n_obs = n())
## `summarise()` has grouped output by 'air_temp_c_NA'. You can override using the
## `.groups` argument.
## # A tibble: 4 × 5
## # Groups:   air_temp_c_NA [2]
##   air_temp_c_NA humidity_NA wind_ew_mean wind_ew_sd n_obs
##   <fct>         <fct>              <dbl>      <dbl> <int>
## 1 !NA           !NA                -4.01       1.74   565
## 2 !NA           NA                 -3.24       2.31    90
## 3 NA            !NA                -2.06       2.08    78
## 4 NA            NA                 -4.97       1.74     3

##Visualizando los valores faltantes de una variable

###Datos nabulares y llenado por valores faltantes

Los estadísticos de resumen son útiles para calcular, pero como dicen, una imagen vale más que mil palabras.

En este ejercicio, vamos a explorar cómo puedes utilizar datos nabular para explorar la variación en una variable según los valores faltantes de otra.

Vamos a utilizar el conjunto de datos oceanbuoys de naniar.

# First explore the missingness structure of `oceanbuoys` using `vis_miss()`
vis_miss(oceanbuoys)

# Explore the distribution of `wind_ew` for the missingness  
# of `air_temp_c_NA` using  `geom_density()`
bind_shadow(oceanbuoys) %>%
  ggplot(aes(x = wind_ew, 
             color = air_temp_c_NA)) + 
  geom_density()

# Explore the distribution of sea temperature for the  
# missingness of humidity (humidity_NA) using  `geom_density()`
bind_shadow(oceanbuoys) %>%
  ggplot(aes(x = sea_temp_c,
             color = humidity_NA)) + 
  geom_density()
## Warning: Removed 3 rows containing non-finite values (stat_density).

Ahora puedes utilizar datos nabulares para visualizar y explorar datos faltantes utilizando gráficos de densidad.

###Datos nabulares y resumen por valores faltantes

En este ejercicio, vamos a explorar cómo utilizar datos nabular para explorar la variación en una variable según los valores faltantes de otra.

Vamos a utilizar el conjunto de datos oceanbuoys de naniar, y luego crear múltiples gráficos de los datos utilizando facetas.

Esto te permite explorar diferentes capas de valores faltantes.

# Explore the distribution of wind east west (wind_ew) for the missingness of air temperature 
# using geom_density() and faceting by the missingness of air temperature (air_temp_c_NA).
oceanbuoys %>%
  bind_shadow() %>%
  ggplot(aes(x = wind_ew)) + 
  geom_density() + 
  facet_wrap(~air_temp_c_NA)

# Build upon this visualization by filling by the missingness of humidity (humidity_NA).
oceanbuoys %>%
  bind_shadow() %>%
  ggplot(aes(x = wind_ew,
             color = humidity_NA)) + 
  geom_density() + 
  facet_wrap(~air_temp_c_NA)

Ahora puedes utilizar datos nabulares para visualizar y explorar datos faltantes.

###Explorar variación por valores faltantes: gráficos de caja

Los ejercicios anteriores utilizan datos nabular junto con gráficos de densidad para explorar la variación en una variable según los valores faltantes de otra.

Vamos a utilizar el conjunto de datos oceanbuoys de naniar, utilizando gráficos de caja en lugar de facetas u otros para explorar diferentes capas de valores faltantes.

# Explore the distribution of wind east west (`wind_ew`) for  
# the missingness of air temperature using  `geom_boxplot()`
oceanbuoys %>%
  bind_shadow() %>%
  ggplot(aes(x = air_temp_c_NA,
             y = wind_ew)) + 
  geom_boxplot()

# Build upon this visualization by faceting by the missingness of humidity (`humidity_NA`).
oceanbuoys %>%
  bind_shadow() %>%
  ggplot(aes(x = air_temp_c_NA,
             y = wind_ew)) + 
  geom_boxplot() + 
  facet_wrap(~humidity_NA)

Ahora puedes utilizar datos nabulares para visualizar y explorar datos faltantes con gráficos de caja y envolturas de facetas.

##Visualizar valores faltantes en dos variables

###Explorando datos faltantes con gráficos de dispersión

Los valores faltantes en un gráfico de dispersión en ggplot2 se eliminan por defecto, con una advertencia.

Podemos mostrar los valores faltantes en un gráfico de dispersión utilizando geom_miss_point() - una geometría especial de ggplot2 que desplaza los valores faltantes dentro del gráfico, mostrándolos un 10% por debajo del mínimo de la variable.

Practiquemos esta visualización con el conjunto de datos oceanbuoys.

# Explore the missingness in wind and air temperature, and  
# display the missingness using `geom_miss_point()`
ggplot(oceanbuoys,
       aes(x = wind_ew,
           y = air_temp_c)) + 
  geom_miss_point()

# Explore the missingness in humidity and air temperature,  
# and display the missingness using `geom_miss_point()`
ggplot(oceanbuoys,
       aes(x = humidity,
           y = air_temp_c)) + 
  geom_miss_point()

###Usando facetas para explorar valores faltantes

Debido a que geom_miss_point() es una geometría de ggplot, puedes usarla con características de ggplot2 como el uso de facetas.

Esto significa que podemos explorar rápidamente los valores faltantes y permanecer dentro de los límites familiares de ggplot2.

# Explore the missingness in wind and air temperature, and display the 
# missingness using `geom_miss_point()`. Facet by year to explore this further.
ggplot(oceanbuoys,
       aes(x = wind_ew,
           y = air_temp_c)) + 
  geom_miss_point() + 
  facet_wrap(~year)

# Explore the missingness in humidity and air temperature, and display the 
# missingness using `geom_miss_point()` Facet by year to explore this further.
ggplot(oceanbuoys,
       aes(x = humidity,
           y = air_temp_c)) + 
  geom_miss_point() + 
  facet_wrap(~year)

Ahora puedes usar geom_miss_point() para explorar valores faltantes en un gráfico de dispersión y puedes usar facetas para expandir y explorar aún más.

###Facetas para explorar valores faltantes (múltiples gráficos) Otra técnica útil con geom_miss_point() es explorar los valores faltantes creando múltiples gráficos.

Así como lo hemos hecho en ejercicios anteriores, podemos usar los datos nabulares para ayudarnos a crear gráficos facetados adicionales.

Incluso podemos crear múltiples gráficos facetados según los valores en los datos, como el año, y las características de los datos, como la falta de valores.

# Use geom_miss_point() and facet_wrap to explore how the missingness 
# in wind_ew and air_temp_c is different for missingness of humidity
bind_shadow(oceanbuoys) %>%
  ggplot(aes(x = wind_ew,
           y = air_temp_c)) + 
  geom_miss_point() + 
  facet_wrap(~humidity_NA)

# Use geom_miss_point() and facet_grid to explore how the missingness in wind_ew and air_temp_c 
# is different for missingness of humidity AND by year - by using `facet_grid(humidity_NA ~ year)`
bind_shadow(oceanbuoys) %>%
  ggplot(aes(x = wind_ew,
             y = air_temp_c)) + 
  geom_miss_point() + 
  facet_grid(humidity_NA~year)

##Realizando y rastreando imputaciones.

###Imputar datos por debajo del rango con datos nulos. Queremos hacer un seguimiento de los valores que imputamos. Si no lo hacemos, es muy difícil evaluar qué tan buenos son los valores imputados.

Vamos a practicar imputando datos y recreando visualizaciones en el conjunto de ejercicios anterior mediante la imputación de valores por debajo del rango de los datos.

Esta es una forma muy útil de ayudar a explorar aún más la falta de datos y también proporciona el marco para imputar valores faltantes.

Primero, vamos a imputar los datos por debajo del rango usando impute_below_all(), y luego visualizar los datos. Notamos que aunque podemos ver dónde están los valores faltantes en este caso, necesitamos alguna forma de hacer un seguimiento de ellos. El patrón de programación de seguimiento de datos faltantes puede ayudar con esto.

# Impute the data below the range using `impute_below`.
ocean_imp <- impute_below_all(oceanbuoys)

# Visualize the new missing values
ggplot(ocean_imp,
       aes(x = wind_ew, y = air_temp_c)) + 
  geom_point()

# Impute and track data with `bind_shadow`, `impute_below`, and `add_label_shadow`
ocean_imp_track <- bind_shadow(oceanbuoys) %>% 
  impute_below_all() %>%
  add_label_shadow()

# Look at the imputed values
ocean_imp_track
## # A tibble: 736 × 17
##     year latit…¹ longi…² sea_t…³ air_t…⁴ humid…⁵ wind_ew wind_ns year_NA latit…⁶
##    <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl> <fct>   <fct>  
##  1  1997       0    -110    27.6    27.1    79.6   -6.40    5.40 !NA     !NA    
##  2  1997       0    -110    27.5    27.0    75.8   -5.30    5.30 !NA     !NA    
##  3  1997       0    -110    27.6    27      76.5   -5.10    4.5  !NA     !NA    
##  4  1997       0    -110    27.6    26.9    76.2   -4.90    2.5  !NA     !NA    
##  5  1997       0    -110    27.6    26.8    76.4   -3.5     4.10 !NA     !NA    
##  6  1997       0    -110    27.8    26.9    76.7   -4.40    1.60 !NA     !NA    
##  7  1997       0    -110    28.0    27.0    76.5   -2       3.5  !NA     !NA    
##  8  1997       0    -110    28.0    27.1    78.3   -3.70    4.5  !NA     !NA    
##  9  1997       0    -110    28.0    27.2    78.6   -4.20    5    !NA     !NA    
## 10  1997       0    -110    28.0    27.2    76.9   -3.60    3.5  !NA     !NA    
## # … with 726 more rows, 7 more variables: longitude_NA <fct>,
## #   sea_temp_c_NA <fct>, air_temp_c_NA <fct>, humidity_NA <fct>,
## #   wind_ew_NA <fct>, wind_ns_NA <fct>, any_missing <chr>, and abbreviated
## #   variable names ¹​latitude, ²​longitude, ³​sea_temp_c, ⁴​air_temp_c, ⁵​humidity,
## #   ⁶​latitude_NA

###Visualizar valores imputados en un gráfico de dispersión.

Ahora, vamos a recrear uno de los gráficos anteriores que vimos en el capítulo tres que utilizaba geom_miss_point().

Para hacer esto, necesitamos imputar los datos por debajo del rango de los datos. Esta es una imputación especial para explorar los datos. Esta imputación ilustrará lo que necesitamos practicar: cómo hacer un seguimiento de los valores faltantes. Para imputar los datos por debajo del rango de los datos, usamos la función impute_below_all().

# Impute and track the missing values
ocean_imp_track <- bind_shadow(oceanbuoys) %>% 
  impute_below_all() %>%
  add_label_shadow()

# Visualize the missingness in wind and air temperature,  
# coloring missing air temp values with air_temp_c_NA
ggplot(ocean_imp_track,
       aes(x = wind_ew, y = air_temp_c, color = air_temp_c_NA)) + 
  geom_point()

# Visualize humidity and air temp, coloring any missing cases using the variable any_missing
ggplot(ocean_imp_track,
       aes(x = humidity, y = air_temp_c, color = any_missing)) + 
  geom_point()

###Crear un histograma de los datos imputados.

Ahora que podemos recrear la primera visualización de geom_miss_point(), vamos a explorar cómo podemos aplicar esto a otras tareas exploratorias.

Una tarea útil es evaluar el número de valores faltantes en una variable dada usando un histograma. Podemos hacer esto usando el conjunto de datos ocean_imp_track que creamos en el último ejercicio, el cual está cargado en esta sesión.

# Explore the values of air_temp_c, visualizing the amount of missings with `air_temp_c_NA`.
p <- ggplot(ocean_imp_track, aes(x = air_temp_c, fill = air_temp_c_NA)) + geom_histogram()

# Expore the missings in humidity using humidity_NA
p2 <- ggplot(ocean_imp_track, aes(x = humidity, fill = humidity_NA)) + geom_histogram()

# Explore the missings in air_temp_c according to year, using `facet_wrap(~year)`.
p + facet_wrap(~year)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

# Explore the missings in humidity according to year, using `facet_wrap(~year)`.
p2 + facet_wrap(~year)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

¿Qué hace una buena imputación?

###Evaluando imputaciones malas.

Para evaluar imputaciones, es útil saber cómo se ve algo malo. Para explorar esto, veamos un método de imputación típicamente malo: imputar usando el valor promedio.

En este ejercicio vamos a explorar cómo funciona el método de imputación de promedio usando un diagrama de caja, utilizando el conjunto de datos oceanbuoys.

# Impute the mean value and track the imputations 
ocean_imp_mean <- bind_shadow(oceanbuoys) %>% 
  impute_mean_all() %>% 
  add_label_shadow()

# Explore the mean values in humidity in the imputed dataset
ggplot(ocean_imp_mean, 
       aes(x = humidity_NA, y = humidity)) + 
  geom_boxplot()

# Explore the values in air temperature in the imputed dataset
ggplot(ocean_imp_mean, 
       aes(x = air_temp_c_NA, y = air_temp_c)) + 
  geom_boxplot()

### Evaluating imputations: The scale

Si bien la imputación de la media puede no parecer tan mala cuando la comparamos mediante un diagrama de caja, es importante tener una idea de la variación en los datos. Es por eso que es importante explorar cómo cambia la escala y la dispersión de los valores imputados en comparación con los datos.

Una forma de evaluar la adecuación de la escala de las imputaciones es usar un gráfico de dispersión para explorar si los valores son apropiados o no.

# Explore imputations in air temperature and humidity,  
# coloring by the variable, any_missing
ggplot(ocean_imp_mean, 
       aes(x = air_temp_c, y = humidity, color = any_missing)) + 
  geom_point()

# Explore imputations in air temperature and humidity,  
# coloring by the variable, any_missing, and faceting by year
ggplot(ocean_imp_mean, 
       aes(x = air_temp_c, y = humidity, color = any_missing)) +
  geom_point() + 
  facet_wrap(~year)

###Evaluando imputaciones: en muchas variables.

Hasta ahora, hemos cubierto formas de ver las variables individuales o pares de variables y sus valores imputados. Sin embargo, a veces deseamos ver las imputaciones para muchas variables. Para hacer esto, es necesario realizar algún tratamiento de datos y reorganización. Esta lección cubre cómo realizar este procesamiento de datos, que puede ser un poco complicado cuando se considera su uso en datos nabular. La función shadow_long() coloca los datos en la forma adecuada para este tipo de visualizaciones.

# Gather the imputed data 
ocean_imp_mean_gather <- shadow_long(ocean_imp_mean,
                                     humidity,
                                     air_temp_c)
# Inspect the data
ocean_imp_mean_gather
## # A tibble: 1,472 × 4
##    variable   value       variable_NA   value_NA
##    <chr>      <chr>       <chr>         <chr>   
##  1 air_temp_c 27.14999962 air_temp_c_NA !NA     
##  2 air_temp_c 27.02000046 air_temp_c_NA !NA     
##  3 air_temp_c 27          air_temp_c_NA !NA     
##  4 air_temp_c 26.93000031 air_temp_c_NA !NA     
##  5 air_temp_c 26.84000015 air_temp_c_NA !NA     
##  6 air_temp_c 26.94000053 air_temp_c_NA !NA     
##  7 air_temp_c 27.04000092 air_temp_c_NA !NA     
##  8 air_temp_c 27.11000061 air_temp_c_NA !NA     
##  9 air_temp_c 27.20999908 air_temp_c_NA !NA     
## 10 air_temp_c 27.25       air_temp_c_NA !NA     
## # … with 1,462 more rows
ocean_imp_mean_gather$value<-as.numeric(ocean_imp_mean_gather$value)


# Explore the imputations in a histogram 
ggplot(ocean_imp_mean_gather, 
       aes(x = value, fill = value_NA)) + 
  geom_histogram() + 
  facet_wrap(~variable)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Realizando imputaciones.

###Utilizando simputation para imputar datos.

Existen muchos paquetes de imputación en R. Nos enfocaremos en usar el paquete simputation, que proporciona una interfaz simple y potente para realizar imputaciones.

Construir un buen modelo de imputación es muy importante, pero es un tema complejo: hay tanto para construir un buen modelo de imputación como para construir un buen modelo estadístico. En este curso, nos enfocaremos en cómo evaluar las imputaciones.

Primero, vamos a ver cómo utilizar la función impute_lm(), que imputa valores de acuerdo a un modelo lineal especificado.

En este ejercicio, vamos a aplicar las técnicas de evaluación anteriores a los datos con impute_lm(), y luego construir sobre este método de imputación en lecciones posteriores.

library(simputation)
## 
## Attaching package: 'simputation'
## The following object is masked from 'package:naniar':
## 
##     impute_median
# Impute humidity and air temperature using wind_ew and wind_ns, and track missing values
ocean_imp_lm_wind <- oceanbuoys %>% 
    bind_shadow() %>%
    impute_lm(air_temp_c ~ wind_ew + wind_ns) %>% 
    impute_lm(humidity ~ wind_ew + wind_ns) %>%
    add_label_shadow()
    
# Plot the imputed values for air_temp_c and humidity, colored by missingness
ggplot(ocean_imp_lm_wind, 
       aes(x = air_temp_c, y = humidity, color = any_missing)) +
  geom_point()

### Evaluando y comparando imputaciones

Cuando se construye un modelo de imputación, es una buena idea compararlo con otro método. En esta lección, vamos a comparar el conjunto de datos previamente imputados creado utilizando impute_lm() con el conjunto de datos imputados con la media. Ambos conjuntos de datos están incluidos en este ejercicio como ocean_imp_lm_wind y ocean_imp_mean, respectivamente.

# Bind the models together 
bound_models <- bind_rows(mean = ocean_imp_mean,
                          lm_wind = ocean_imp_lm_wind,
                          .id = "imp_model")

# Inspect the values of air_temp and humidity as a scatter plot
ggplot(bound_models,
       aes(x = air_temp_c,
           y = humidity,
           color = any_missing)) +
  geom_point() + 
  facet_wrap(~imp_model)

### Evaluando imputaciones (muchos modelos y variables)

Cuando se construye un modelo de imputación, es una buena idea compararlo con otro método.

En esta lección, se te pedirá que agregues un modelo de imputación final que contenga una pieza adicional de información útil que ayude a explicar parte de la variación en los datos. Luego, compararás los valores, como se hizo anteriormente en la última lección.

# Build a model adding year to the outcome
ocean_imp_lm_wind_year <- bind_shadow(oceanbuoys) %>%
  impute_lm(air_temp_c ~ wind_ew + wind_ns + year) %>%
  impute_lm(humidity ~ wind_ew + wind_ns + year) %>%
  add_label_shadow()

# Bind the mean, lm_wind, and lm_wind_year models together
bound_models <- bind_rows(mean = ocean_imp_mean,
                          lm_wind = ocean_imp_lm_wind,
                          lm_wind_year = ocean_imp_lm_wind_year,
                          .id = "imp_model")

# Explore air_temp and humidity, coloring by any missings, and faceting by imputation model
ggplot(bound_models, aes(x = air_temp_c, y = humidity, color = any_missing)) +
  geom_point() + facet_wrap(~imp_model)

Evaluando imputaciones y modelos

###Combinación y comparación de muchos modelos de imputación

Para evaluar los diferentes métodos de imputación, necesitamos ponerlos en un único dataframe. A continuación, compararás tres enfoques diferentes para manejar los datos faltantes utilizando el conjunto de datos oceanbuoys.

El primer método es utilizar solo los casos completados y se carga como ocean_cc. El segundo método es imputar valores utilizando un modelo lineal con predicciones hechas con wind y se carga como ocean_imp_lm_wind. Crearás el tercer conjunto de datos imputados, ocean_imp_lm_all, utilizando un modelo lineal e imputando las variables sea_temp_c, air_temp_c y humidity utilizando las variables wind_ew, wind_ns, year, latitude y longitude.

Luego unirás todos los conjuntos de datos (ocean_cc, ocean_imp_lm_wind y ocean_imp_lm_all), llamándolo bound_models.

ocean_cc<-oceanbuoys %>%
na.omit() %>%
bind_shadow %>%
add_label_shadow()
# Create an imputed dataset using a linear models
ocean_imp_lm_all <- bind_shadow(oceanbuoys) %>%
  add_label_shadow() %>%
  impute_lm(sea_temp_c ~ wind_ew + wind_ns + year + latitude + longitude) %>%
  impute_lm(air_temp_c ~ wind_ew + wind_ns + year + latitude + longitude) %>%
  impute_lm(humidity ~ wind_ew + wind_ns + year + latitude + longitude)

# Bind the datasets
bound_models <- bind_rows(cc = ocean_cc,
                          imp_lm_wind = ocean_imp_lm_wind,
                          imp_lm_all = ocean_imp_lm_all,
                          .id = "imp_model")

# Look at the models
bound_models
## # A tibble: 2,037 × 18
##    imp_m…¹  year latit…² longi…³ sea_t…⁴ air_t…⁵ humid…⁶ wind_ew wind_ns year_NA
##    <chr>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl> <fct>  
##  1 cc       1997       0    -110    27.6    27.1    79.6   -6.40    5.40 !NA    
##  2 cc       1997       0    -110    27.5    27.0    75.8   -5.30    5.30 !NA    
##  3 cc       1997       0    -110    27.6    27      76.5   -5.10    4.5  !NA    
##  4 cc       1997       0    -110    27.6    26.9    76.2   -4.90    2.5  !NA    
##  5 cc       1997       0    -110    27.6    26.8    76.4   -3.5     4.10 !NA    
##  6 cc       1997       0    -110    27.8    26.9    76.7   -4.40    1.60 !NA    
##  7 cc       1997       0    -110    28.0    27.0    76.5   -2       3.5  !NA    
##  8 cc       1997       0    -110    28.0    27.1    78.3   -3.70    4.5  !NA    
##  9 cc       1997       0    -110    28.0    27.2    78.6   -4.20    5    !NA    
## 10 cc       1997       0    -110    28.0    27.2    76.9   -3.60    3.5  !NA    
## # … with 2,027 more rows, 8 more variables: latitude_NA <fct>,
## #   longitude_NA <fct>, sea_temp_c_NA <fct>, air_temp_c_NA <fct>,
## #   humidity_NA <fct>, wind_ew_NA <fct>, wind_ns_NA <fct>, any_missing <chr>,
## #   and abbreviated variable names ¹​imp_model, ²​latitude, ³​longitude,
## #   ⁴​sea_temp_c, ⁵​air_temp_c, ⁶​humidity

Evaluando los diferentes parámetros en el modelo

stamos imputando nuestros datos por una razón: ¡queremos analizar los datos!

En este ejemplo, estamos interesados en predecir la temperatura del mar, así que vamos a construir un modelo lineal que prediga la temperatura del mar.

Ajustaremos este modelo a cada uno de los conjuntos de datos que creamos y luego exploraremos los coeficientes en los datos.

Los objetos de la lección anterior (ocean_cc, ocean_imp_lm_wind, ocean_imp_lm_all y bound_models) se cargan en el espacio de trabajo.

# Create the model summary for each dataset
model_summary <- bound_models %>% 
  group_by(imp_model) %>%
  nest() %>%
  mutate(mod = purrr::map(data, ~lm(sea_temp_c ~ air_temp_c + humidity + year, data = .)),
         res = purrr::map(mod, residuals),
         pred = purrr::map(mod, predict),
         tidy = purrr::map(mod, broom::tidy))

# Explore the coefficients in the model
model_summary %>% 
    select(imp_model,tidy) %>%
    unnest()
## Warning: `cols` is now required when using unnest().
## Please use `cols = c(tidy)`
## # A tibble: 12 × 6
## # Groups:   imp_model [3]
##    imp_model   term          estimate std.error statistic   p.value
##    <chr>       <chr>            <dbl>     <dbl>     <dbl>     <dbl>
##  1 cc          (Intercept)  -735.      45.9        -16.0  8.19e- 48
##  2 cc          air_temp_c      0.864    0.0231      37.4  2.64e-154
##  3 cc          humidity        0.0341   0.00390      8.74 2.69e- 17
##  4 cc          year            0.369    0.0232      15.9  3.46e- 47
##  5 imp_lm_wind (Intercept) -1742.      56.1        -31.0  1.83e-135
##  6 imp_lm_wind air_temp_c      0.365    0.0279      13.1  2.73e- 35
##  7 imp_lm_wind humidity        0.0225   0.00690      3.26 1.17e-  3
##  8 imp_lm_wind year            0.880    0.0283      31.1  6.79e-136
##  9 imp_lm_all  (Intercept)  -697.      51.8        -13.5  5.04e- 37
## 10 imp_lm_all  air_temp_c      0.890    0.0255      35.0  2.90e-158
## 11 imp_lm_all  humidity        0.0127   0.00463      2.75 6.03e-  3
## 12 imp_lm_all  year            0.351    0.0262      13.4  1.12e- 36
best_model <- "imp_lm_all"